﻿// CreateOrEditSpaceTypeViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using RevitProject.SpaceManager.Configuration; // CategoryNodeConfig
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using Autodesk.Revit.DB.Analysis;
using System.Diagnostics;
using RevitProject.SpaceManager.ViewModel.SpaceViewModel;

namespace RevitProject.SpaceManager.ViewModel.DialogViewModelPart
{
   
    /// <summary>
    /// 数据传输对象 (DTO)，用于在创建/编辑空间类型的对话框 ViewModel 和 Service 层之间传递用户输入的数据。
    /// 所有参数值都以字符串形式存储，以便 Service 层进行统一的解析和单位转换。
    /// </summary>
    public class SpaceTypeUserInputData
    {
        // --- 核心信息 ---
        /// <summary>空间类型的名称。</summary>
        public string Name { get; set; }

        /// <summary>用户在对话框中选择的目标父分类节点 ViewModel 引用。如果添加到根，则为 null。</summary>
        public SpaceTypeTreeNodeViewModel SelectedParentNode { get; set; }

        // --- HVAC 负荷参数 (字符串形式的用户输入) ---
        /// <summary>人均面积 (用户输入，预期单位 m²/人)。</summary>
        public string AreaPerPerson { get; set; }

        /// <summary>照明负荷密度 (用户输入，预期单位 W/m²)。</summary>
        public string LightingLoadDensity { get; set; }

        /// <summary>设备负荷密度 (用户输入，预期单位 W/m²)。</summary>
        public string PowerLoadDensity { get; set; }

        /// <summary>人员显热 (用户输入，预期单位 W/人)。</summary>
        public string SensibleHeatGainPerPerson { get; set; }

        /// <summary>人员潜热 (用户输入，预期单位 W/人)。</summary>
        public string LatentHeatGainPerPerson { get; set; }

        /// <summary>供暖设定点 (用户输入，预期单位 °C)。</summary>
        public string HeatingSetpoint { get; set; }

        /// <summary>制冷设定点 (用户输入，预期单位 °C)。</summary>
        public string CoolingSetpoint { get; set; }

        /// <summary>加湿设定点 (用户输入，预期单位 %)。</summary>
        public string HumidificationSetpoint { get; set; }

        /// <summary>除湿设定点 (用户输入，预期单位 %)。</summary>
        public string DehumidificationSetpoint { get; set; }

        /// <summary>每区域的渗透风量 (用户输入，预期单位 L/(s·m²))。</summary>
        public string InfiltrationAirflowPerArea { get; set; }

        // --- 明细表 ---
        /// <summary>用户选择的占用率明细表名称 (如果选择了"无"，则为 null)。</summary>
        public string OccupancySchedule { get; set; }

        /// <summary>用户选择的照明明细表名称 (如果选择了"无"，则为 null)。</summary>
        public string LightingSchedule { get; set; }

        /// <summary>用户选择的电力负荷明细表名称 (如果选择了"无"，则为 null)。</summary>
        public string PowerSchedule { get; set; }

        // --- 新风参数 ---
        /// <summary>每人新风量 (用户输入，预期单位 m³/h 或 L/s)。</summary>
        // Service 层需要知道预期的输入单位来进行转换。
        public string OutsideAirPerPerson { get; set; }

        /// <summary>每面积新风量 (用户输入，预期单位 L/(s·m²))。</summary>
        public string OutsideAirPerArea { get; set; }

        /// <summary>每小时换气次数 (用户输入，预期单位 次/h)。</summary>
        public string AirChangesPerHour { get; set; }

        /// <summary>用户选择的新风方法 (中文名称或其他标识符)。</summary>
        public string OutsideAirMethod { get; set; }

        // --- 编辑模式专用信息 ---
        /// <summary>如果要编辑的现有空间类型的 ElementId；如果是创建新类型，则为 null。</summary>
        public ElementId ExistingTypeId { get; set; } = null;

        /// <summary>编辑模式下，空间类型的原始名称 (用于 JSON 更新)。</summary>
        public string OriginalName { get; set; }

        /// <summary>编辑模式下，空间类型原始的父节点 ViewModel 引用 (用于 JSON 更新)。</summary>
        public SpaceTypeTreeNodeViewModel OriginalParentNode { get; set; }

        // --- 可以根据需要添加更多属性 ---
        // 例如：反射率、构造类型等，如果这些也允许用户在对话框中输入的话。
    }


    public partial class CreateOrEditSpaceTypeViewModel : ObservableObject
    {
        // --- 核心信息 ---
        private string _name;
        /// <summary>空间类型名称。</summary>
        public string Name { get => _name; set => SetProperty(ref _name, value); }

        private ObservableCollection<SpaceTypeTreeNodeViewModel> _availableParentNodes = new ObservableCollection<SpaceTypeTreeNodeViewModel>();
        /// <summary>可选的父分类节点列表。</summary>
        public ObservableCollection<SpaceTypeTreeNodeViewModel> AvailableParentNodes { get => _availableParentNodes; private set => SetProperty(ref _availableParentNodes, value); }

        private SpaceTypeTreeNodeViewModel _selectedParentNode;
        /// <summary>用户选择的父分类节点。</summary>
        public SpaceTypeTreeNodeViewModel SelectedParentNode { get => _selectedParentNode; set => SetProperty(ref _selectedParentNode, value); }

        // --- HVAC 负荷参数 (基于 HVACLoadItemViewModel，使用 string 接收输入) ---

        // IsPlenumDisplay -> IsPlenum (Boolean, 通常不可编辑，但可以在 ViewModel 中保存状态)
        private bool _isPlenum = false; // 默认为 false
        /// <summary>指示是否为静压箱 (通常不可编辑)。</summary>
        public bool IsPlenum { get => _isPlenum; private set => SetProperty(ref _isPlenum, value); } // 只在加载编辑数据时设置

        private string _areaPerPerson = "10.0";
        /// <summary>人均面积 (输入值，单位：m²/人)。</summary>
        public string AreaPerPerson { get => _areaPerPerson; set => SetProperty(ref _areaPerPerson, value); }

        private string _lightingLoadDensity = "8.0";
        /// <summary>照明负荷密度 (输入值，单位：W/m²)。</summary>
        public string LightingLoadDensity { get => _lightingLoadDensity; set => SetProperty(ref _lightingLoadDensity, value); }

        private string _powerLoadDensity = "10.0";
        /// <summary>设备负荷密度 (输入值，单位：W/m²)。</summary>
        public string PowerLoadDensity { get => _powerLoadDensity; set => SetProperty(ref _powerLoadDensity, value); }

        private string _sensibleHeatGainPerPerson = "75";
        /// <summary>人员显热 (输入值，单位：W/人)。</summary>
        public string SensibleHeatGainPerPerson { get => _sensibleHeatGainPerPerson; set => SetProperty(ref _sensibleHeatGainPerPerson, value); }

        private string _latentHeatGainPerPerson = "55";
        /// <summary>人员潜热 (输入值，单位：W/人)。</summary>
        public string LatentHeatGainPerPerson { get => _latentHeatGainPerPerson; set => SetProperty(ref _latentHeatGainPerPerson, value); }

        private string _heatingSetpoint = "20";
        /// <summary>供暖设定点 (输入值，单位：°C)。</summary>
        public string HeatingSetpoint { get => _heatingSetpoint; set => SetProperty(ref _heatingSetpoint, value); }

        private string _coolingSetpoint = "24";
        /// <summary>制冷设定点 (输入值，单位：°C)。</summary>
        public string CoolingSetpoint { get => _coolingSetpoint; set => SetProperty(ref _coolingSetpoint, value); }

        private string _humidificationSetpoint = "30"; // 默认值示例
        /// <summary>加湿设定点 (输入值，单位：%)。</summary>
        public string HumidificationSetpoint { get => _humidificationSetpoint; set => SetProperty(ref _humidificationSetpoint, value); }

        private string _dehumidificationSetpoint = "60"; // 默认值示例
        /// <summary>除湿设定点 (输入值，单位：%)。</summary>
        public string DehumidificationSetpoint { get => _dehumidificationSetpoint; set => SetProperty(ref _dehumidificationSetpoint, value); }

        private string _infiltrationAirflowPerArea = "0.1"; // 默认值示例
        /// <summary>每区域的渗透风量 (输入值，单位：L/(s·m²))。</summary>
        public string InfiltrationAirflowPerArea { get => _infiltrationAirflowPerArea; set => SetProperty(ref _infiltrationAirflowPerArea, value); }

        // --- 明细表 (需要 ComboBox 选择) ---
        private ObservableCollection<string> _availableSchedules = new ObservableCollection<string>();
        /// <summary>项目中可用的明细表名称列表 (包括 "无")。</summary>
        public ObservableCollection<string> AvailableSchedules { get => _availableSchedules; private set => SetProperty(ref _availableSchedules, value); }

        private string _selectedOccupancySchedule = "无"; // 默认无
        /// <summary>用户选择的占用率明细表名称。</summary>
        public string SelectedOccupancySchedule { get => _selectedOccupancySchedule; set => SetProperty(ref _selectedOccupancySchedule, value); }

        private string _selectedLightingSchedule = "无"; // 默认无
        /// <summary>用户选择的照明明细表名称。</summary>
        public string SelectedLightingSchedule { get => _selectedLightingSchedule; set => SetProperty(ref _selectedLightingSchedule, value); }

        private string _selectedPowerSchedule = "无"; // 默认无
        /// <summary>用户选择的电力负荷明细表名称。</summary>
        public string SelectedPowerSchedule { get => _selectedPowerSchedule; set => SetProperty(ref _selectedPowerSchedule, value); }

        // --- 新风参数 ---
        private string _outsideAirPerPerson = "8.5"; // 默认值示例
        /// <summary>每人新风量 (输入值，单位：m³/h 或 L/s，取决于你的界面单位)。</summary>
        //    注意：界面单位要明确，以便 Service 层正确转换。假设界面用 m³/h   
        public string OutsideAirPerPerson { get => _outsideAirPerPerson; set => SetProperty(ref _outsideAirPerPerson, value); }

        private string _outsideAirPerArea = "0.3"; // 默认值示例
        /// <summary>每面积新风量 (输入值，单位：L/(s·m²))。</summary>
        public string OutsideAirPerArea { get => _outsideAirPerArea; set => SetProperty(ref _outsideAirPerArea, value); }

        private string _airChangesPerHour = "0.5"; // 默认值示例
        /// <summary>每小时换气次数 (输入值，单位：次/h)。</summary>
        public string AirChangesPerHour { get => _airChangesPerHour; set => SetProperty(ref _airChangesPerHour, value); }

        // --- 新风方法 (需要 ComboBox 选择) ---
        private ObservableCollection<string> _availableOutsideAirMethods = new ObservableCollection<string>();
        /// <summary>可选的新风方法列表 (中文名称)。</summary>
        public ObservableCollection<string> AvailableOutsideAirMethods { get => _availableOutsideAirMethods; private set => SetProperty(ref _availableOutsideAirMethods, value); }

        private string _selectedOutsideAirMethod = "按人数和面积"; // 默认值示例
        /// <summary>用户选择的新风方法 (中文名称)。</summary>
        public string SelectedOutsideAirMethod { get => _selectedOutsideAirMethod; set => SetProperty(ref _selectedOutsideAirMethod, value); }


        // --- 模式标记和标题 (手动实现) ---
        private bool _isEditing = false;
        public bool IsEditing { get => _isEditing; private set => SetProperty(ref _isEditing, value); }
        private string _title = "创建新空间类型";
        public string Title { get => _title; private set => SetProperty(ref _title, value); }

        // --- 存储原始数据 (编辑模式, 保持 private) ---
        private ElementId _existingTypeId = null;
        private string _originalName = null;
        private SpaceTypeTreeNodeViewModel _originalParentNode = null;



        

        public CreateOrEditSpaceTypeViewModel()
        {
            // 初始化明细表和新风方法列表 (这里是硬编码示例，实际应从 Document 获取)
            LoadAvailableSchedules(null); // 稍后在 Initialize 时传入 Document
            LoadAvailableOutsideAirMethods();
        }

        /// <summary>
        /// 初始化用于创建新类型。
        /// </summary>
        /// <param name="preselectedParent">从树右键菜单传入的预选父节点。</param>
        /// <param name="allPossibleParents">所有可选的父节点列表 (非叶节点)。</param>
        // --- 初始化方法 ---
        public void InitializeForCreate(SpaceTypeTreeNodeViewModel preselectedParent, IEnumerable<SpaceTypeTreeNodeViewModel> allPossibleParents, Document doc)
        {
            IsEditing = false;
            Title = "创建新空间类型";
            Name = "新空间类型";
            // 设置其他参数的默认值 (已在属性声明中设置)

            InitializeParentNodes(preselectedParent, allPossibleParents);
            LoadAvailableSchedules(doc); // 从文档加载明细表
        }

        public void InitializeForEdit(HVACLoadSpaceType spaceTypeToEdit, SpaceTypeTreeNodeViewModel currentParentNode, IEnumerable<SpaceTypeTreeNodeViewModel> allPossibleParents, Document doc)
        {
            IsEditing = true;
            Title = $"编辑空间类型: {spaceTypeToEdit.Name}";
            _existingTypeId = spaceTypeToEdit.Id;
            _originalName = spaceTypeToEdit.Name;
            _originalParentNode = currentParentNode;

            // 加载现有值
            Name = spaceTypeToEdit.Name;
            IsPlenum = spaceTypeToEdit.IsPlenum; // 设置 IsPlenum 状态
            AreaPerPerson = ConvertToDisplayString(spaceTypeToEdit.AreaPerPerson, UnitTypeId.SquareMeters, "F1");
            LightingLoadDensity = ConvertToDisplayString(spaceTypeToEdit.LightingLoadDensity, UnitTypeId.WattsPerSquareMeter, "F1");
            PowerLoadDensity = ConvertToDisplayString(spaceTypeToEdit.PowerLoadDensity, UnitTypeId.WattsPerSquareMeter, "F1");
            SensibleHeatGainPerPerson = ConvertToDisplayString(spaceTypeToEdit.SensibleHeatGainPerPerson, UnitTypeId.Watts, "F0");
            LatentHeatGainPerPerson = ConvertToDisplayString(spaceTypeToEdit.LatentHeatGainPerPerson, UnitTypeId.Watts, "F0");
            HeatingSetpoint = ConvertToDisplayString(spaceTypeToEdit.HeatingSetPoint, UnitTypeId.Celsius, "F0");
            CoolingSetpoint = ConvertToDisplayString(spaceTypeToEdit.CoolingSetPoint, UnitTypeId.Celsius, "F0");
            HumidificationSetpoint = UnitUtils.ConvertFromInternalUnits(spaceTypeToEdit.HumidificationSetPoint, UnitTypeId.Percentage).ToString("F0"); // 转换为百分比显示
            // 注意： HumidificationSetPoint 和 DehumidificationSetPoint 是以百分比存储的
            DehumidificationSetpoint = UnitUtils.ConvertFromInternalUnits(spaceTypeToEdit.DehumidificationSetPoint, UnitTypeId.Percentage).ToString("F0"); // 转换为百分比显示

            InfiltrationAirflowPerArea = ConvertToDisplayString(spaceTypeToEdit.get_Parameter(BuiltInParameter.SPACE_INFILTRATION_PARAM)?.AsDouble(), UnitTypeId.LitersPerSecondSquareMeter, "F2"); // 获取参数值

            OutsideAirPerPerson = ConvertToDisplayString(spaceTypeToEdit.OutdoorAirPerPerson, UnitTypeId.CubicMetersPerHour, "F1");

            OutsideAirPerArea = ConvertToDisplayString(spaceTypeToEdit.OutdoorAirPerArea, UnitTypeId.LitersPerSecondSquareMeter, "F2");

            AirChangesPerHour = ConvertToDisplayString(spaceTypeToEdit.AirChangesPerHour, null, "F2");

            InitializeParentNodes(currentParentNode, allPossibleParents);
            LoadAvailableSchedules(doc); // 加载明细表

            // 设置选中的明细表和新风方法
            SelectedOccupancySchedule = GetScheduleNameFromParam(spaceTypeToEdit, BuiltInParameter.SPACE_OCCUPANCY_SCHEDULE_PARAM) ?? "无";
            SelectedLightingSchedule = GetScheduleNameFromParam(spaceTypeToEdit, BuiltInParameter.SPACE_LIGHTING_SCHEDULE_PARAM) ?? "无";
            SelectedPowerSchedule = GetScheduleNameFromParam(spaceTypeToEdit, BuiltInParameter.SPACE_POWER_SCHEDULE_PARAM) ?? "无";
            SelectedOutsideAirMethod = ConvertOutdoorAirStandardToDisplay(spaceTypeToEdit.OutdoorAirFlowStandard);
        }


        //// <summary>
        /// 验证用户输入。
        /// </summary>
        /// <param name="doc">Revit 文档对象，用于检查名称唯一性。</param>
        /// <returns>如果验证通过则返回 true，否则显示错误消息并返回 false。</returns>
        public bool ValidateInput(Document doc)
        {
            if (doc == null)
            {
                MessageBox.Show("验证输入时发生内部错误：文档对象无效。", "验证错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return false;
            }

            List<string> errors = new List<string>();

            // --- 1. 验证名称 ---
            Name = Name?.Trim();
            if (string.IsNullOrWhiteSpace(Name))
            {
                errors.Add("空间类型名称不能为空。");
            }
            // 检查名称唯一性 (仅在新建或编辑时名称改变的情况下)
            else if (!IsEditing || IsEditing && !Name.Equals(_originalName ?? "", StringComparison.OrdinalIgnoreCase))
            {
                try // 包裹 Revit API 调用
                {
                    bool isNameUnique = !new FilteredElementCollector(doc)
                                            .OfClass(typeof(HVACLoadSpaceType))
                                            .WhereElementIsElementType()
                                            .Any(el => el.Id != _existingTypeId && // 编辑时排除自身
                                                       el.Name.Equals(Name, StringComparison.OrdinalIgnoreCase));
                    if (!isNameUnique)
                    {
                        errors.Add($"名称 '{Name}' 已被另一个空间类型使用，请输入唯一名称。");
                    }
                }
                catch (Exception ex)
                {
                    errors.Add($"检查名称唯一性时出错: {ex.Message}");
                    Debug.WriteLine($"Error checking name uniqueness: {ex}");
                }
            }

            // --- 2. 验证父节点选择 ---
            // (通常不需要，因为 ComboBox 会有选中项)
            // if (SelectedParentNode == null || SelectedParentNode.DisplayName == "(添加到根分类)" || SelectedParentNode.DisplayName == "(根分类)")
            // {
            //     errors.Add("必须选择一个有效的父分类（不能是根选项）。");
            // }


            // --- 3. 验证数值输入 ---
            double tempDouble;
            double tempPercent;
            double heatingTemp = double.NaN; // 初始化为 NaN，表示尚未成功解析
            double coolingTemp = double.NaN;

            // 人均面积
            if (!string.IsNullOrWhiteSpace(AreaPerPerson) && (!double.TryParse(AreaPerPerson, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("人均面积必须是有效的非负数字。");
            // 照明负荷密度
            if (!string.IsNullOrWhiteSpace(LightingLoadDensity) && (!double.TryParse(LightingLoadDensity, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("照明负荷密度必须是有效的非负数字。");
            // 设备负荷密度
            if (!string.IsNullOrWhiteSpace(PowerLoadDensity) && (!double.TryParse(PowerLoadDensity, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("设备负荷密度必须是有效的非负数字。");
            // 人员显热
            if (!string.IsNullOrWhiteSpace(SensibleHeatGainPerPerson) && (!double.TryParse(SensibleHeatGainPerPerson, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("人员显热必须是有效的非负数字。");
            // 人员潜热
            if (!string.IsNullOrWhiteSpace(LatentHeatGainPerPerson) && (!double.TryParse(LatentHeatGainPerPerson, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("人员潜热必须是有效的非负数字。");

            // 供暖设定点 (允许为空或数字)
            bool heatingParsed = false;
            if (!string.IsNullOrWhiteSpace(HeatingSetpoint))
            {
                if (!double.TryParse(HeatingSetpoint, NumberStyles.Any, CultureInfo.InvariantCulture, out heatingTemp)) errors.Add("供暖设定点必须是有效的数字。");
                else heatingParsed = true;
            }

            // 制冷设定点 (允许为空或数字)
            bool coolingParsed = false;
            if (!string.IsNullOrWhiteSpace(CoolingSetpoint))
            {
                if (!double.TryParse(CoolingSetpoint, NumberStyles.Any, CultureInfo.InvariantCulture, out coolingTemp)) errors.Add("制冷设定点必须是有效的数字。");
                else coolingParsed = true;
            }

            // 加湿设定点 (允许为空或 0-100 数字)
            if (!string.IsNullOrWhiteSpace(HumidificationSetpoint) && (!double.TryParse(HumidificationSetpoint.Replace("%", ""), NumberStyles.Any, CultureInfo.InvariantCulture, out tempPercent) || tempPercent < 0 || tempPercent > 100)) errors.Add("加湿设定点必须是 0 到 100 之间的有效数字。");
            // 除湿设定点 (允许为空或 0-100 数字)
            if (!string.IsNullOrWhiteSpace(DehumidificationSetpoint) && (!double.TryParse(DehumidificationSetpoint.Replace("%", ""), NumberStyles.Any, CultureInfo.InvariantCulture, out tempPercent) || tempPercent < 0 || tempPercent > 100)) errors.Add("除湿设定点必须是 0 到 100 之间的有效数字。");
            // 渗透风量 (允许为空或非负数字)
            if (!string.IsNullOrWhiteSpace(InfiltrationAirflowPerArea) && (!double.TryParse(InfiltrationAirflowPerArea, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("渗透风量必须是有效的非负数字。");
            // 每人新风量 (允许为空或非负数字)
            if (!string.IsNullOrWhiteSpace(OutsideAirPerPerson) && (!double.TryParse(OutsideAirPerPerson, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("每人新风量必须是有效的非负数字。");
            // 每面积新风量 (允许为空或非负数字)
            if (!string.IsNullOrWhiteSpace(OutsideAirPerArea) && (!double.TryParse(OutsideAirPerArea, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("每面积新风量必须是有效的非负数字。");
            // 换气次数 (允许为空或非负数字)
            if (!string.IsNullOrWhiteSpace(AirChangesPerHour) && (!double.TryParse(AirChangesPerHour, NumberStyles.Any, CultureInfo.InvariantCulture, out tempDouble) || tempDouble < 0)) errors.Add("换气次数必须是有效的非负数字。");


            // --- 4. 检查温度逻辑关系 (仅当两者都成功解析时) ---
            if (heatingParsed && coolingParsed && coolingTemp <= heatingTemp)
            {
                errors.Add("制冷设定点必须高于供暖设定点。");
            }

            // --- 5. 检查下拉框选择 ---
            // (通常 ComboBox 会保证选中有效项，所以这里的检查是可选的，除非你想强制用户不能选某些项，比如"无")
            // if (SelectedOccupancySchedule == null || SelectedOccupancySchedule == "无") errors.Add("必须选择一个占用率明细表。"); // 示例：强制选择
            // if (SelectedOutsideAirMethod == null) errors.Add("必须选择一个新风方法。");


            // --- 6. 显示错误信息 ---
            if (errors.Any())
            {
                MessageBox.Show("请修正以下错误:\n\n- " + string.Join("\n- ", errors), // 使用 MessageBox 提供更清晰的错误列表
                               "输入验证失败", MessageBoxButton.OK, MessageBoxImage.Warning);
                return false;
            }

            // 所有验证通过
            return true;
        }



        /// <summary>
        /// 将用户输入转换为包含 Revit 内部单位的 DTO。
        /// </summary>
        /// <returns>转换后的 DTO，如果转换失败则返回 null。</returns>
        public SpaceTypeUserInputData GetResultData()
        {
            // 将当前 ViewModel 的属性值收集到 DTO 中
            var data = new SpaceTypeUserInputData
            {
                Name = Name,
                SelectedParentNode = SelectedParentNode?.DisplayName == "(添加到根分类)" || SelectedParentNode?.DisplayName == "(根分类)" ? null : SelectedParentNode,
                ExistingTypeId = _existingTypeId,
                OriginalName = _originalName,
                OriginalParentNode = _originalParentNode,

                // 直接传递 string 值，让 Service 层处理解析和转换
                AreaPerPerson = AreaPerPerson,
                LightingLoadDensity = LightingLoadDensity,
                PowerLoadDensity = PowerLoadDensity,
                SensibleHeatGainPerPerson = SensibleHeatGainPerPerson,
                LatentHeatGainPerPerson = LatentHeatGainPerPerson,
                HeatingSetpoint = HeatingSetpoint,
                CoolingSetpoint = CoolingSetpoint,
                HumidificationSetpoint = HumidificationSetpoint,
                DehumidificationSetpoint = DehumidificationSetpoint,
                InfiltrationAirflowPerArea = InfiltrationAirflowPerArea,
                OccupancySchedule = SelectedOccupancySchedule == "无" ? null : SelectedOccupancySchedule,
                LightingSchedule = SelectedLightingSchedule == "无" ? null : SelectedLightingSchedule,
                PowerSchedule = SelectedPowerSchedule == "无" ? null : SelectedPowerSchedule,
                OutsideAirPerPerson = OutsideAirPerPerson,
                OutsideAirPerArea = OutsideAirPerArea,
                AirChangesPerHour = AirChangesPerHour,
                OutsideAirMethod = SelectedOutsideAirMethod,
            };
            return data;
        }

        // --- 辅助方法 ---

        // 初始化父节点下拉列表
        private void InitializeParentNodes(SpaceTypeTreeNodeViewModel preselectedParent, IEnumerable<SpaceTypeTreeNodeViewModel> allPossibleParents)
        {
            AvailableParentNodes.Clear();
            var rootOption = new SpaceTypeTreeNodeViewModel(IsEditing ? "(根分类)" : "(添加到根分类)", ElementId.InvalidElementId);
            AvailableParentNodes.Add(rootOption);
            if (allPossibleParents != null)
            {
                foreach (var node in allPossibleParents) AvailableParentNodes.Add(node);
            }
            SelectedParentNode = AvailableParentNodes.FirstOrDefault(n => n == preselectedParent) ?? rootOption;
        }


        // 加载可选明细表列表
        private void LoadAvailableSchedules(Document doc)
        {
            AvailableSchedules.Clear();
            AvailableSchedules.Add("无"); // 添加“无”选项
            if (doc != null)
            {
                try
                {
                    var schedules = new FilteredElementCollector(doc)
                        .OfClass(typeof(ViewSchedule))
                        .WhereElementIsNotElementType()
                        .Cast<ViewSchedule>()      
                        .OrderBy(vs => vs.Name)
                        .Select(vs => vs.Name)
                        .ToList();
                    foreach (var name in schedules)
                    {
                        AvailableSchedules.Add(name);
                    }
                }
                catch (Exception ex) { Debug.WriteLine($"加载明细表列表时出错: {ex.Message}"); }
            }
        }
        // 加载可选新风方法列表 (硬编码中文)
        private void LoadAvailableOutsideAirMethods()
        {
            AvailableOutsideAirMethods.Clear();
            // 这些中文需要与 Service 层或 Revit API 枚举的映射关系一致
            AvailableOutsideAirMethods.Add("按人数和面积");
            AvailableOutsideAirMethods.Add("按换气次数");
            AvailableOutsideAirMethods.Add("最大值 (按人数, 按面积)");
            AvailableOutsideAirMethods.Add("最大值 (按换气次数, 按人数和面积)");
            AvailableOutsideAirMethods.Add("最大值 (按换气次数, 按面积, 按人数)");
            // 添加更多枚举对应的中文描述...
            SelectedOutsideAirMethod = AvailableOutsideAirMethods.FirstOrDefault(); // 默认选中第一个
        }


        // 从 Revit 值转换为显示字符串
        private string ConvertToDisplayString(double? internalValueNullable, ForgeTypeId displayUnitTypeId, string format)
        {
            if (!internalValueNullable.HasValue) return ""; // 返回空字符串而不是 "错误"
            double internalValue = internalValueNullable.Value;
            try
            {
                if (displayUnitTypeId != null && !string.IsNullOrEmpty(displayUnitTypeId.TypeId))
                {
                    double displayValue = UnitUtils.ConvertFromInternalUnits(internalValue, displayUnitTypeId);
                    return displayValue.ToString(format, CultureInfo.InvariantCulture);
                }
                else
                {
                    return internalValue.ToString(format, CultureInfo.InvariantCulture);
                }
            }
            catch { return "转换错误"; } // 转换出错时返回错误提示
        }
        // 重载用于不需要单位转换的 double
        private string ConvertToDisplayString(double internalValue, ForgeTypeId displayUnitTypeId, string format)
        {
            return ConvertToDisplayString((double?)internalValue, displayUnitTypeId, format);
        }
        // 重载用于不需要单位转换的 double
        private string ConvertToDisplayString(double? internalValueNullable, string displayUnitTypeId, string format) // 单位参数改为 string 或 null
        {
            return ConvertToDisplayString(internalValueNullable, (ForgeTypeId)null, format); // 调用核心方法，传 null 单位
        }


        // 从参数获取明细表名称
        private string GetScheduleNameFromParam(HVACLoadSpaceType spaceType, BuiltInParameter bip)
        {
            try
            {
                Parameter param = spaceType?.get_Parameter(bip);
                ElementId scheduleId = param?.AsElementId();
                if (spaceType.Document != null && scheduleId != null && scheduleId != ElementId.InvalidElementId)
                {
                    var schedule = spaceType.Document.GetElement(scheduleId);
                    return schedule?.Name;
                }
            }
            catch (Exception ex) { Debug.WriteLine($"获取明细表名称时出错 ({bip}): {ex.Message}"); }
            return null; // 返回 null 表示未找到或出错
        }

        // 将 API 的 OutdoorAirFlowStandard 枚举转换为用于显示的中文（需要与 LoadAvailableOutsideAirMethods 一致）
        private string ConvertOutdoorAirStandardToDisplay(OutdoorAirFlowStandard standard)
        {
            switch (standard)
            {
                case OutdoorAirFlowStandard.ByPeopleAndByArea: return "按人数和面积";
                case OutdoorAirFlowStandard.ByACH: return "按换气次数";
                case OutdoorAirFlowStandard.MaxByPeople_ByArea: return "最大值 (按人数, 按面积)";
                case OutdoorAirFlowStandard.MaxByACH_ByPeopleByArea: return "最大值 (按换气次数, 按人数和面积)";
                case OutdoorAirFlowStandard.MaxByACH_ByArea_ByPeople: return "最大值 (按换气次数, 按面积, 按人数)";
                // 添加其他枚举值的映射...
                default: return standard.ToString(); // 默认返回枚举名称
            }
        }
    }
}